package ast

import (
	"errors"
	"fmt"
	"github.com/davecgh/go-spew/spew"
	"log/slog"
	"regexp"
	"rule/data"
	"rule/model"
	"strconv"
	"strings"
)

func ConvertRuleRaw2RuleDef(_ruleRaw *model.RuleRaw) (*model.RuleDef, error) {
	ruleDef := &model.RuleDef{}
	ruleDef.Id = _ruleRaw.Id
	ruleDef.RuleId = _ruleRaw.RuleId
	ruleDef.Status = _ruleRaw.Status
	ruleDef.AlarmTime = _ruleRaw.AlarmTime
	ruleDef.PtIdList = _ruleRaw.PtIdList
	ruleDef.ExpressionList = _ruleRaw.ExpressionList
	ruleDef.RuleExpression = _ruleRaw.RuleExpression
	ruleDef.LinkageList = _ruleRaw.LinkageList

	// 目前都是, 三者对齐按顺序
	var pointDurs []pointDur
	re := regexp.MustCompile(`_\d+@\d+`)
	tmpArray := strings.Split(_ruleRaw.PtIdList, ",")
	for _, tmpOne := range tmpArray {
		if re.MatchString(tmpOne) {
			tmp := strings.Split(tmpOne, "@")
			ptId := strings.TrimPrefix(tmp[0], "_")
			dur, _ := strconv.Atoi(tmp[1])
			pointDurs = append(pointDurs, pointDur{ptId, dur})
		}
	}
	re = nil
	tmpArray = strings.Split(_ruleRaw.ExpressionList, ",")
	if len(pointDurs) != len(tmpArray) {
		return nil, errors.New("规则异常无法解析,规则list,2个长度对不上")
	}
	// ptIdList, exprList, ruleExpr string
	newRuleExpr := _ruleRaw.RuleExpression
	_ruleItems := make([]model.RuleItem, len(tmpArray))
	//
	for i, tmpOne := range tmpArray {
		//
		if !strings.HasPrefix(tmpOne, "${_"+pointDurs[i].Ptid+"}") {
			return nil, errors.New("规则异常,ptId对不上,Prefix异常" + tmpOne)
		}
		// 替换表达式
		boolStr := "b_" + strconv.Itoa(i)
		newRuleExpr = strings.Replace(newRuleExpr, tmpOne, boolStr, 1)
		//
		_ruleItems[i].PtId = pointDurs[i].Ptid
		_ruleItems[i].Duration = pointDurs[i].Dur
		_ruleItems[i].BoolAbbr = boolStr
		// 判断依据
		if strings.Contains(tmpOne, "count") {
			tmpOne2 := strings.TrimPrefix(tmpOne, "${_"+pointDurs[i].Ptid+"}")
			leftExpr, countExpr, err := analysisCountRule(tmpOne2)
			//
			if err != nil {
				return nil, errors.New("count规则异常:" + err.Error())
			}
			//
			_ruleItems[i].Type = model.RuleTypeCount
			_ruleItems[i].LeftExpr = leftExpr
			_ruleItems[i].CountExpr = countExpr
			//
		} else if strings.Contains(tmpOne, "change") {
			left, right, changeExpr, err := analysisChangeToRule(tmpOne)
			//slog.Debug("特别特别" + fmt.Sprintf("left:%s,right%s,changeExpr:%s,err:%v", left, right, changeExpr, err))
			if err != nil {
				return nil, errors.New("change规则异常:" + err.Error())
			}
			//
			_ruleItems[i].Type = model.RuleTypeChange
			_ruleItems[i].Left = left
			_ruleItems[i].Right = right
			_ruleItems[i].ChangeExpr = changeExpr
		} else {
			expr := "%v" + strings.TrimPrefix(tmpOne, "${_"+pointDurs[i].Ptid+"}")
			_ruleItems[i].Type = model.RuleTypeNormal
			_ruleItems[i].LeftExpr = expr
		}
		//
		gloAddPtId(_ruleItems[i].PtId)
	}

	ruleDef.BoolExpr = newRuleExpr
	ruleDef.RuleItems = _ruleItems

	// 反控点位挑选出来
	for _, _linkage := range _ruleRaw.LinkageList {
		data.CtrlPtId.Add(_linkage.PtId)
	}

	slog.Warn("rule def data", "ruleDef", *ruleDef)
	// dump 日志
	spew.Dump(*ruleDef)

	// 这个函数结束时候，下一个函数，把规则加入全局变量 rule_list, 并且在时间轮轮里面新增任务
	return ruleDef, nil
}

// 新增规则的时候需要触发
func gloAddPtId(ptid string) {
	data.MapPtId.Add(ptid)
	data.QueueMap.AddQueue(ptid)
}

type pointDur struct {
	Ptid string
	Dur  int
}

// 废弃 单元测试的
func GetRuleItem(ptIdList, exprList, ruleExpr string) (any, error) {

	// '_2000844574@16,_2000844574@16,_2000896154@60,_2000896155@60,_2000844573@97,_2000844574@16',
	// '((${_2000844574} == 1 || ${_2000844574} == 0) && (${_2000896154} == 0 && ${_2000896155} == 0 && ${_2000844573} change 0 to 1 change >= 6) && ${_2000844574} >= 0 count >= 15)
	// '${_2000844574} == 1,${_2000844574} == 0,${_2000896154} == 0,${_2000896155} == 0,${_2000844573} change 0 to 1 change >= 6,${_2000844574} >= 0 count >= 15'
	// 表达式替换压缩 ((b_0 || b_1) && (b_2 && b_3 && b_4) && b_5)

	// 正则表达式 _\d+@\d+

	// 按顺序
	var pointDurs []pointDur
	re := regexp.MustCompile(`_\d+@\d+`)
	tmpArray := strings.Split(ptIdList, ",")
	for _, tmpOne := range tmpArray {
		if re.MatchString(tmpOne) {
			tmp := strings.Split(tmpOne, "@")
			ptId := strings.TrimPrefix(tmp[0], "_")
			dur, _ := strconv.Atoi(tmp[1])
			fmt.Println(ptId, dur)
			pointDurs = append(pointDurs, pointDur{ptId, dur})
		}
	}
	re = nil
	//
	fmt.Println("------------------")
	tmpArray = strings.Split(exprList, ",")
	if len(pointDurs) != len(tmpArray) {
		fmt.Println("规则list, 异常无法解析, 2个长度对不上")
		return nil, nil
	}
	for i, tmpOne := range tmpArray {
		//
		if !strings.HasPrefix(tmpOne, "${_"+pointDurs[i].Ptid+"}") {
			return nil, errors.New("规则异常,ptId对不上,Prefix异常" + tmpOne)
		}

		// 替换表达式
		boolStr := "b_" + strconv.Itoa(i)
		ruleExpr = strings.Replace(ruleExpr, tmpOne, boolStr, 1)

		// 判断依据
		if strings.Contains(tmpOne, "count") {
			// ${_2000844574} >= 0 count >= 15 切割
			tmpOne2 := strings.TrimPrefix(tmpOne, "${_"+pointDurs[i].Ptid+"}")
			leftExpr, countExpr, err := analysisCountRule(tmpOne2)
			// leftExpr, countExpr string, err error
			fmt.Println("count表达式结果", leftExpr, countExpr, err)

		} else if strings.Contains(tmpOne, "change") {
			// ${_2000844573} change 0 to 1 change >= 6
			// ptid pointDurs[i].Ptid
			left, right, changeExpr, err := analysisChangeToRule(tmpOne)
			if err != nil {
				return nil, err
			}
			fmt.Println("change表达式结果", left, right, changeExpr, err)
		} else {
			// ${_2000844574} == 0 普通规则
			// "${_"+pointDurs[i].Ptid+"}"
			expr := "%v" + strings.TrimPrefix(tmpOne, "${_"+pointDurs[i].Ptid+"}")
			fmt.Println("normal表达式结果", expr)
		}
		fmt.Println("calc expr", tmpOne)
	}
	fmt.Println("------------------")

	newruleExpr := ruleExpr
	fmt.Println(newruleExpr)
	//fmt.Println(pointDurs)
	return nil, nil
}

// 	parts := strings.Split(rawExpr, "change")
//	if len(parts) != 3 {
//		err = errors.New("规则异常,len异常" + rawExpr)
//		return
//	}

func analysisCountRule(rawExpr string) (leftExpr, countExpr string, err error) {
	// ${_2000844574} >= 0 count >= 15 切割
	parts := strings.Split(rawExpr, "count")
	if len(parts) != 2 {
		err = errors.New("规则异常,len异常" + rawExpr)
		return
	}
	leftExpr = "%v " + strings.TrimSpace(parts[0])
	countExpr = "%v " + strings.TrimSpace(parts[1])
	return
}

func analysisChangeToRule(rawExpr string) (left, right, changeExpr string, err error) {
	parts := strings.Split(rawExpr, "change")
	if len(parts) != 3 {
		err = errors.New("规则异常,len异常" + rawExpr)
		return
	}
	lr := strings.Split(parts[1], "to")
	if len(lr) != 2 {
		err = errors.New("规则异常,切to异常" + rawExpr)
		return
	}
	left = strings.TrimSpace(lr[0])
	right = strings.TrimSpace(lr[1])
	changeExpr = "%v " + strings.TrimSpace(parts[2])
	return
}

// "{\"datas\":[{\"ptid\":\"1000104490\",\"result\":\"0\"},{\"ptid\":\"1000104491\",\"result\":\"0\"},{\"ptid\":\"1000104492\",\"result\":\"1\"},{\"ptid\":\"1000104493\",\"result\":\"1\"},{\"ptid\":\"1000104494\",\"result\":\"95\"},{\"ptid\":\"1000104495\",\"result\":\"54\"},{\"ptid\":\"1000104496\",\"result\":\"16\"},{\"ptid\":\"1000104497\",\"result\":\"48\"},{\"ptid\":\"1000104498\",\"result\":\"0\"}],\"epid\":\"2000000007\",\"gwid\":\"1773175679715975170\",\"timestamp\":\"1721982140041\"}"
